home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / util / misc / ClipHandler1_0.lha / Src / clip-handler.c
Encoding:
C/C++ Source or Header  |  1995-03-29  |  9.9 KB  |  399 lines

  1. /*
  2. **    clip-handler.c
  3. **    DOS handler for Clipboard access
  4. **    Copyright © 1995 Michael Letowski
  5. */
  6.  
  7. #define __USE_SYSBASE
  8.  
  9. #include <exec/types.h>
  10. #include <exec/execbase.h>
  11. #include <exec/memory.h>
  12. #include <dos/dos.h>
  13. #include <dos/dosextens.h>
  14. #include <dos/filehandler.h>
  15. #include <libraries/iffparse.h>
  16. #include <devices/clipboard.h>
  17. #include <support/types.h>
  18. #include <support/exec.h>
  19. #include <support/dos.h>
  20.  
  21. #include <string.h>
  22. #include <stdlib.h>
  23.  
  24. #include <proto/exec.h>
  25. #include <proto/iffparse.h>
  26.  
  27. #include "clip-handler.rev.h"
  28.  
  29. #define DOS_NAME        "dos.library"
  30. #define DOS_VERN         37L
  31. #define IFFP_NAME        "iffparse.library"
  32. #define IFFP_VERN        37L
  33. #define CLIP_NAME        "clipboard.device"
  34.  
  35. STATIC CONST TEXT VersionString[]=
  36.     VERSION(PROG_NAME,PROG_VERSION,PROG_REVISION,PROG_DATE);
  37.  
  38. #define ID_FTXT            MAKE_ID('F','T','X','T')
  39. #define ID_CHRS            MAKE_ID('C','H','R','S')
  40.  
  41. #define PATH_SIZE        256
  42.  
  43. /* Library bases */
  44. struct ExecBase *SysBase;
  45. struct Library *IFFParseBase;
  46.  
  47. STATIC struct DosPacket *WaitPacket(struct MsgPort *port);
  48. STATIC VOID ReplyPacket(struct DosPacket *packet, struct MsgPort *port);
  49. STATIC VOID ReplyPacketRes(struct DosPacket *packet, struct MsgPort *port,
  50.                                                         LONG res1, LONG res2);
  51. STATIC struct IFFHandle *OpenCH(struct DosPacket *packet);
  52. STATIC VOID CloseCH(struct IFFHandle *iff);
  53. STATIC LONG OpenInputCH(struct DosPacket *packet);
  54. STATIC LONG OpenOutputCH(struct DosPacket *packet);
  55. STATIC LONG OpenUpdateCH(struct DosPacket *packet);
  56. STATIC LONG CloseIOUCH(struct DosPacket *packet);
  57. STATIC VOID ReadClipboard(struct DosPacket *packet);
  58. STATIC VOID WriteClipboard(struct DosPacket *packet);
  59. STATIC VOID SeekClipboard(struct DosPacket *packet);
  60. STATIC LONG IFF2DOS(LONG iffError);
  61.  
  62. SAVEDS LONG ClipHandler(VOID)
  63. {
  64.     struct Library *LocalIFFParseBase;
  65.  
  66.     struct Process *PR;
  67.     struct MsgPort *MP,*PacketPort;
  68.     struct DosPacket *Pkt;
  69.     struct DeviceNode *DevNode;
  70.     LBOOL Done=FALSE;
  71.     ULONG OpenCount=0;
  72.  
  73.     SysBase=*((struct ExecBase **)4);                            /* Set up SysBase */
  74.     PR=ThisProcessS;
  75.     MP=&PR->pr_MsgPort;
  76.  
  77.     if(PR->pr_CLI)                                                                /* Run from shell */
  78.         return(RETURN_FAIL);                                                /* Failure */
  79.  
  80.     Pkt=WaitPacket(MP);                                                        /* Get startup message */
  81.     try(DevNode=(struct DeviceNode *)BADDR(Pkt->dp_Arg3),NO_DEV);
  82.  
  83.     /* Open IFFParse */
  84.     unless(LocalIFFParseBase=OpenLibrary(IFFP_NAME,IFFP_VERN))
  85.     {
  86.         ReplyPacketRes(Pkt,MP,DOSFALSE,ERROR_INVALID_RESIDENT_LIBRARY);
  87.         throw(NO_IFFPARSE);
  88.     }
  89.     /* Create port */
  90.     unless(PacketPort=CreateMsgPort())
  91.     {
  92.         ReplyPacketRes(Pkt,MP,DOSFALSE,ERROR_NO_FREE_STORE);
  93.         throw(NO_PORT);
  94.     }
  95.     /* Set up global bases */
  96.     IFFParseBase=LocalIFFParseBase;                                /* Set up global bases */
  97.     DevNode->dn_Task=PacketPort;
  98.     Pkt->dp_Arg4=(LONG)PacketPort;
  99.     ReplyPacketRes(Pkt,PacketPort,DOSTRUE,Pkt->dp_Res2);
  100.  
  101.     while(!Done)
  102.     {
  103.         Pkt=WaitPacket(PacketPort);
  104.         switch(Pkt->dp_Type)
  105.         {
  106.             case ACTION_FINDINPUT:
  107.                 OpenCount+=OpenInputCH(Pkt);
  108.                 break;
  109.             case ACTION_FINDOUTPUT:
  110.                 OpenCount+=OpenOutputCH(Pkt);
  111.                 break;
  112. /*            case ACTION_FINDUPDATE:
  113.                 OpenCount+=OpenUpdateCH(Pkt);*/
  114.                 break;
  115.             case ACTION_END:
  116.                 OpenCount-=CloseIOUCH(Pkt);
  117.                 break;
  118.             case ACTION_READ:
  119.                 ReadClipboard(Pkt);
  120.                 break;
  121.             case ACTION_WRITE:
  122.                 WriteClipboard(Pkt);
  123.                 break;
  124. /*            case ACTION_SEEK:
  125.                 SeekClipboard(Pkt);*/
  126.                 break;
  127.             case ACTION_DIE:
  128.                 if(OpenCount)
  129.                 {
  130.                     Pkt->dp_Res1=DOSFALSE;
  131.                     Pkt->dp_Res2=ERROR_OBJECT_IN_USE;
  132.                 }
  133.                 else
  134.                 {
  135.                     Pkt->dp_Res1=DOSTRUE;
  136.                     Pkt->dp_Res2=0;
  137.                     Done=TRUE;
  138.                 }
  139.             case ACTION_IS_FILESYSTEM:
  140.                 Pkt->dp_Res1=DOSFALSE;
  141.                 Pkt->dp_Res2=0;
  142.                 break;
  143.             default:
  144.                 Pkt->dp_Res1=DOSFALSE;
  145.                 Pkt->dp_Res2=ERROR_ACTION_NOT_KNOWN;
  146.                 break;
  147.         }
  148.         ReplyPacket(Pkt,PacketPort);
  149.     }
  150.     DevNode->dn_Task=NULL;                                                /* Switch off device */
  151.  
  152.     except(NO_PORT,DeleteMsgPort(PacketPort));
  153.     except(NO_IFFPARSE,CloseLibrary(LocalIFFParseBase));
  154.     except(NO_DEV,);
  155.     return(0);
  156. }    /* ClipHandler */
  157.  
  158. STATIC struct DosPacket *WaitPacket(struct MsgPort *port)
  159. {
  160.     WaitPort(port);
  161.     return((struct DosPacket *)GetMsg(port)->mn_Node.ln_Name);
  162. }    /* WaitPacket */
  163.  
  164. STATIC VOID ReplyPacket(struct DosPacket *packet, struct MsgPort *port)
  165. {
  166.     struct MsgPort *ReplyPort=packet->dp_Port;
  167.  
  168.     packet->dp_Port=port;
  169.     packet->dp_Link->mn_Node.ln_Name=(STRPTR)packet;
  170.     PutMsg(ReplyPort,packet->dp_Link);
  171. }    /* ReplyPacket */
  172.  
  173. STATIC VOID ReplyPacketRes(struct DosPacket *packet, struct MsgPort *port,
  174.                                                         LONG res1, LONG res2)
  175. {
  176.     packet->dp_Res1=res1;
  177.     packet->dp_Res2=res2;
  178.     ReplyPacket(packet,port);
  179. }    /* ReplyPacketRes */
  180.  
  181. STATIC struct IFFHandle *OpenCH(struct DosPacket *packet)
  182. {
  183.     CHAR Name[PATH_SIZE];
  184.     STRPTR Str=(STRPTR)BADDR(packet->dp_Arg3);
  185.     struct FileHandle *Handle=FH(packet->dp_Arg1);
  186.     struct IFFHandle *IFF;
  187.     LONG Unit;
  188.  
  189.     packet->dp_Res1=DOSFALSE;
  190.     packet->dp_Res2=0;
  191.     Handle->fh_Arg1=0;
  192.     Handle->fh_Port=NULL;                                                    /* Non-interactive file */
  193.  
  194.     memcpy(Name,&Str[1],Str[0]);                                    /* Copy data */
  195.     Name[Str[0]]='\0';                                                        /* NULL-terminate */
  196.  
  197.     Str=Name;
  198.     if(Str=strchr(Str,':'))                                                /* Device name given */
  199.         Str++;                                                                            /* Skip it */
  200.     Unit=atol(Str);                                                                /* Convert to unit number */
  201.  
  202.     unless(IFF=AllocIFF())
  203.     {
  204.         packet->dp_Res2=ERROR_NO_FREE_STORE;
  205.         throw(NO_IFF);
  206.     }
  207.     unless(IFF->iff_Stream=(ULONG)OpenClipboard(Unit))
  208.     {
  209.         packet->dp_Res2=ERROR_NO_FREE_STORE;                /* FIX!!! */
  210.         throw(NO_CLIPBOARD);
  211.     }
  212.     InitIFFasClip(IFF);
  213.     Handle->fh_Arg1=(LONG)IFF;
  214.     packet->dp_Res1=DOSTRUE;
  215.     return(IFF);
  216.  
  217.     except(NO_CLIPBOARD,CloseClipboard((struct ClipboardHandle *)IFF->iff_Stream));
  218.     except(NO_IFF,FreeIFF(IFF));
  219.     return(NULL);
  220. }    /* OpenCH */
  221.  
  222. STATIC VOID CloseCH(struct IFFHandle *iff)
  223. {
  224.     CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
  225.     FreeIFF(iff);
  226. }    /* CloseCH */
  227.  
  228. STATIC LONG OpenInputCH(struct DosPacket *packet)
  229. {
  230.     struct IFFHandle *IFF;
  231.     LONG Error;
  232.  
  233.     try(IFF=OpenCH(packet),NO_HANDLE);
  234.     try(!(Error=OpenIFF(IFF,IFFF_READ)),NO_IFF);
  235.     try(!(Error=StopChunk(IFF,ID_FTXT,ID_CHRS)),IFF_ERROR);
  236.     try(!(Error=ParseIFF(IFF,IFFPARSE_SCAN)),IFF_ERROR);
  237.     return(1);                                                                        /* Open succesfull */
  238.  
  239.     except(IFF_ERROR,);
  240.     packet->dp_Res1=DOSFALSE;
  241.     packet->dp_Res2=IFF2DOS(Error);                                /* Set result */
  242.     except(NO_IFF,CloseIFF(IFF));
  243.     except(NO_HANDLE,CloseCH(IFF));
  244.     return(0);                                                                        /* Open failed */
  245. }    /* OpenInputCH */
  246.  
  247. STATIC LONG OpenOutputCH(struct DosPacket *packet)
  248. {
  249.     struct IFFHandle *IFF;
  250.     LONG Error;
  251.  
  252.     try(IFF=OpenCH(packet),NO_HANDLE);
  253.     try(!(Error=OpenIFF(IFF,IFFF_WRITE)),NO_IFF);
  254.     try(!(Error=PushChunk(IFF,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN)),IFF_ERROR);
  255.     try(!(Error=PushChunk(IFF,0,ID_CHRS,IFFSIZE_UNKNOWN)),IFF_ERROR);
  256.     return(1);                                                                        /* Open succesfull */
  257.  
  258.     except(IFF_ERROR,);
  259.     packet->dp_Res1=DOSFALSE;
  260.     packet->dp_Res2=IFF2DOS(Error);                                /* Set result */
  261.     except(NO_IFF,CloseIFF(IFF));
  262.     except(NO_HANDLE,CloseCH(IFF));
  263.     return(0);                                                                        /* Open failed */
  264. }    /* OpenOutputCH */
  265.  
  266. STATIC LONG OpenUpdateCH(struct DosPacket *packet)
  267. {
  268.     struct IFFHandle *IFF;
  269.     LONG Error;
  270.  
  271.     try(IFF=OpenCH(packet),NO_HANDLE);
  272.     try(!(Error=OpenIFF(IFF,IFFF_WRITE)),NO_IFF);
  273.     try(!(Error=StopChunk(IFF,ID_FTXT,ID_CHRS)),IFF_ERROR);
  274.     try(!(Error=ParseIFF(IFF,IFFPARSE_SCAN)),IFF_ERROR);    /* FIX: Should use write mode here */
  275.     return(1);                                                                        /* Open succesfull */
  276.  
  277.     except(IFF_ERROR,);
  278.     packet->dp_Res1=DOSFALSE;
  279.     packet->dp_Res2=IFF2DOS(Error);                                /* Set result */
  280.     except(NO_IFF,CloseIFF(IFF));
  281.     except(NO_HANDLE,CloseCH(IFF));
  282.     return(0);                                                                        /* Open failed */
  283. }    /* OpenUpdateCH */
  284.  
  285. STATIC LONG CloseIOUCH(struct DosPacket *packet)
  286. {
  287.     struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
  288.  
  289. #if 0
  290.     /* FIX:??? Check PopChunk() for errors */
  291.     if(ftst(IFF->iff_Flags,IFFF_WRITE))                        /* Write mode */
  292.         if(PopChunk(IFF)==0)                                                /* Close CHRS */
  293.             PopChunk(IFF);                                                        /* Close FTXT */
  294. #endif
  295.     CloseIFF(IFF);
  296.     CloseCH(IFF);
  297.     packet->dp_Res1=DOSTRUE;
  298.     packet->dp_Res2=0;
  299.     return(1);
  300. }    /* CloseIOUCH */
  301.  
  302. STATIC VOID ReadClipboard(struct DosPacket *packet)
  303. {
  304.     struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
  305.     STRPTR Buffer=(STRPTR)packet->dp_Arg2;
  306.     LONG Read=-1,Bytes=packet->dp_Arg3;
  307.  
  308.     packet->dp_Res1=-1;
  309.     packet->dp_Res2=0;
  310.  
  311.     Read=ReadChunkBytes(IFF,Buffer,Bytes);                /* Read into buffer */
  312.     if(Read<0)
  313.         packet->dp_Res2=IFF2DOS(Read);
  314.     else
  315.         packet->dp_Res1=Read;
  316. }    /* ReadClipboard */
  317.  
  318. STATIC VOID WriteClipboard(struct DosPacket *packet)
  319. {
  320.     struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
  321.     STRPTR Buffer=(STRPTR)packet->dp_Arg2;
  322.     LONG Written=-1,Bytes=packet->dp_Arg3;
  323.  
  324.     packet->dp_Res1=-1;
  325.     packet->dp_Res2=0;
  326.  
  327.     Written=WriteChunkBytes(IFF,Buffer,Bytes);        /* Write buffer */
  328.     if(Written<0)
  329.         packet->dp_Res2=IFF2DOS(Written);
  330.     else
  331.         packet->dp_Res1=Written;
  332. }    /* WriteClipboard */
  333.  
  334. STATIC VOID SeekClipboard(struct DosPacket *packet)
  335. {
  336.     struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
  337.     struct ContextNode *CN;
  338.     LONG Offset=packet->dp_Arg2,OffsetType=packet->dp_Arg3;
  339.     LONG OldPos,NewPos=-1;
  340.  
  341.     packet->dp_Res1=-1;
  342.     packet->dp_Res2=ERROR_SEEK_ERROR;
  343.  
  344.     unless(CN=CurrentChunk(IFF))
  345.         return;
  346.     unless(CN->cn_Type==ID_FTXT && CN->cn_ID==ID_CHRS)
  347.         return;
  348.  
  349.     switch(OffsetType)
  350.     {
  351.         case OFFSET_BEGINNING:
  352.             NewPos=Offset;
  353.             break;
  354.         case OFFSET_CURRENT:
  355.             NewPos=CN->cn_Scan+Offset;
  356.             break;
  357.         case OFFSET_END:
  358.             NewPos=CN->cn_Size-Offset;
  359.             break;
  360.     }
  361.     if(NewPos>0 && NewPos<CN->cn_Size)                        /* Can seek */
  362.     {
  363.         OldPos=CN->cn_Scan;
  364.         CN->cn_Scan=NewPos;
  365.         packet->dp_Res1=OldPos;
  366.         packet->dp_Res2=0;
  367.     }
  368. }    /* SeekClipboard */
  369.  
  370. STATIC LONG IFF2DOS(LONG iffError)
  371. {
  372.     LONG DOSError;
  373.  
  374.     switch(iffError)
  375.     {
  376.         case IFFERR_EOF:
  377.         case IFFERR_EOC:
  378.         case IFFERR_NOSCOPE:
  379.         case IFFERR_MANGLED:
  380.         case IFFERR_SYNTAX:
  381.         case IFFERR_NOTIFF:
  382.             DOSError=ERROR_OBJECT_WRONG_TYPE;
  383.             break;
  384.         case IFFERR_NOMEM:
  385.             DOSError=ERROR_NO_FREE_STORE;
  386.             break;
  387.         case IFFERR_SEEK:
  388.             DOSError=ERROR_SEEK_ERROR;
  389.             break;
  390.         case IFFERR_NOHOOK:
  391.             DOSError=ERROR_NOT_IMPLEMENTED;
  392.             break;
  393.         default:
  394.             DOSError=ThisProcessS->pr_Result2;
  395.             break;
  396.     }
  397.     return(DOSError);
  398. }    /* IFF2DOS */
  399.